package org.finesys.common.security.authentication.filter;

import java.io.IOException;
import java.util.Map;

import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.ArrayUtils;
import org.finesys.common.constants.SecurityConstants;
import org.finesys.common.core.servlet.RepeatBodyRequestWrapper;
import org.finesys.common.core.util.StrUtil;
import org.finesys.common.security.core.config.AuthSecurityProperties;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import lombok.RequiredArgsConstructor;

/**
 * 密码解密工具类
 */
@Component
@RequiredArgsConstructor
public class PasswordDecoderFilter extends OncePerRequestFilter {

    private final AuthSecurityProperties authSecurityProperties;
    private static final String PASSWORD = "password";
    private static final String KEY_ALGORITHM = "AES";

    static {
        // 关闭hutool 强制关闭Bouncy Castle库的依赖
        SecureUtil.disableBouncyCastle();
    }

    @Override
    protected void doFilterInternal(@NonNull HttpServletRequest request,@NonNull HttpServletResponse response,@NonNull FilterChain filterChain) throws ServletException, IOException {
        // 不是登录请求，直接向下执行
        if (!StrUtil.containsAnyIgnoreCase(request.getRequestURI(), SecurityConstants.OAUTH_TOKEN_URL)) {
            filterChain.doFilter(request, response);
            return;
        }
        // 将请求流转换为可多次读取的请求流
        RepeatBodyRequestWrapper repeatBodyRequestWrapper = new RepeatBodyRequestWrapper(request);
        Map<String, String[]> parameterMap = repeatBodyRequestWrapper.getParameterMap();
        //构建前端对应解密ARS因子
        AES aes = new AES(Mode.CFB, Padding.NoPadding, new SecretKeySpec(authSecurityProperties.getEncodeKey().getBytes(), KEY_ALGORITHM)
                , new IvParameterSpec(authSecurityProperties.getEncodeKey().getBytes()));
        parameterMap.forEach((k, v) -> {
            String[] value = parameterMap.get(k);
            if (!PASSWORD.equals(k) || ArrayUtils.isEmpty(value)) {
                return;
            }
            //解密密码
            String decryptPassword = aes.decryptStr(value[0]);
            parameterMap.put(k, new String[]{decryptPassword});
        });
        filterChain.doFilter(repeatBodyRequestWrapper, response);
    }
}
